package de.mafr.jsystest.file;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import de.mafr.jsystest.SystemTestException;
import de.mafr.jsystest.utils.Substitution;



import net.sf.json.JSON;
import net.sf.json.JSONSerializer;


/**
 * Utilities for reading test data from files.
 */
public final class FileUtils {
	
	private FileUtils() {
		// nothing to be done
	}
	
	
	/**
	 * Static factory method for a Substitution (for conciseness).
	 */
	public static Substitution s(String src, String dest) {
		return new Substitution(src, dest);
	}
	
	/**
	 * Read JSON from a file relative to the integration test dir.
	 * 
	 * String substitutions are performed in order, if given. 
	 * 
	 * @param fileName the name of a file relative to src/test/resources
	 * @return
	 */	
	public static final JSON jsonFile(String fileName, Substitution... substitutions) {
		String jsonStr = Substitution.substitute(file(fileName), substitutions);
		
		return JSONSerializer.toJSON(jsonStr);
	}
	

	/**
	 * Read a file's contents into a String.
	 * 
	 * The file must be located relative to src/test/resources.
	 * 
	 * TODO: Make sure there are no EOL issues on windows.
	 * TODO: EOF isn't handled correctly, too. We always append "\n".
	 * 
	 * @throws SystemTestException on error
	 */
	public static final String file(String fileName) {
		StringBuilder fileData = new StringBuilder();
		File inputFile = new File("src/test/resources", fileName);
		BufferedReader reader = null;
		
		try {
			reader = new BufferedReader(new FileReader(inputFile));
			
			String line = null;
			while ((line=reader.readLine() )!= null) {
				fileData.append(line);
				fileData.append("\n");
			}
			
		} catch (FileNotFoundException e) {
			throw new SystemTestException("file not found: " + fileName, e);
		} catch (IOException e) {
			throw new SystemTestException("error reading file: " + fileName, e);
		} finally {
			safeClose(reader);
		}

		return fileData.toString();
	}
	
	private static void safeClose(Closeable closeable) {
		if (closeable == null)
			return;
		
		try {
			closeable.close();
		} catch (IOException e) {
			throw new SystemTestException("Cannot close stream");
		}
	}
}
